import { defineComponent, h, PropType, reactive, ref, render, VNode, watch } from 'vue';
import { ElMessageBox, MessageBoxState, ElDialog, ElDrawer, ElButton } from 'element-plus';
import { app } from '@/main';
import { Loading } from '@/global';

export enum DialogType {
  dialog, drawer
}

interface DialogOption {
  dialogType?: DialogType;
  width?: string;// 对话框宽度
  title?: string; // 对话框标题
  teleportDom?: string; // 传送的dom
  defaultSlot: () => VNode | string; // 默认模板
}
declare type footerButtonCallback = (done: () => void, loading: Loading) => void;
export interface DynamicDialogOption extends DialogOption {
  footer?: ((done: () => void) => VNode | string | null)
}

export interface ConfirmDialogOption extends DialogOption {
  confirmCallback:footerButtonCallback;
  cancelCallback?:footerButtonCallback;
  cancelText?: string;
  confirmText?: string;
}

export interface AlertDialogOption extends DialogOption{
  okCallback: footerButtonCallback;
  okText?: string;
}

/**
 * 对话框弹框
 */
const DialogComponent = defineComponent({
  name: 'WindDialog',
  emits: ['close'],
  props: {
    title: { type: String, default: '' },
    width: { type: String, default: '40%' },
    visible: {
      type: Object as PropType<{ status: boolean }>,
      default: () => {
        return { status: false };
      }
    },
    dialogType: { type: Number as PropType<DialogType>, default: DialogType.dialog }
  },
  setup (props, { emit, slots }) {
    const visible = ref<Boolean>(props.visible?.status);
    watch(props, newVal => {
      if (newVal.visible) {
        visible.value = newVal.visible.status;
      }
    });
    const onClose = () => {
      visible.value = false;
      emit('close');
    };
    return () =>
      <div>{props.dialogType === DialogType.dialog
        ? <ElDialog v-model={visible.value} title={props.title} width={props.width} destroyOnClose={true}
                    onClose={onClose} closeOnPressEscape={true} draggable>
          {{ default: slots.default, footer: slots.footer }}
        </ElDialog>
        : <ElDrawer v-model={visible.value} withHeader={true} size={props.width} title={props.title} destroyOnClose={true}
                  onClose={onClose} closeOnPressEscape={true}>
          {{ default: slots.default, footer: slots.footer }}
        </ElDrawer>}
      </div>;
  }
});
/**
 * 生成一个仅有确认跟取消的对话框
 * @param message
 * @param title
 * @param okMethod 点击确认按钮的回调
 */
const windConfirm = (message: VNode | string, title: string, okMethod?: (instance: MessageBoxState, done: () => void) => void) => {
  return ElMessageBox({
    title,
    message,
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    showCancelButton: true,
    showConfirmButton: true,
    draggable: true,
    beforeClose: (action, instance, done) => {
      if (action === 'confirm') {
        if (okMethod) {
          okMethod(instance, done);
        } else {
          done();
        }
      } else {
        done();
      }
    }
  });
};
const windAlertDialog = (dialogOption: AlertDialogOption) => {
  const okLoading = reactive<Loading>({ status: false });
  const okFunction: footerButtonCallback = (done, loading) => {
    if (dialogOption.okCallback) {
      dialogOption.okCallback(done, loading);
    } else {
      done();
    }
  };
  const dynamicDialogOption: DynamicDialogOption = {
    defaultSlot: dialogOption.defaultSlot,
    title: dialogOption.title,
    dialogType: dialogOption.dialogType,
    width: dialogOption.width,
    teleportDom: dialogOption.teleportDom,
    footer: (done: (() => void)) => <div>
      <ElButton type={'default'} loading={okLoading.status} onClick={() => { okFunction(done, okLoading); } }>{dialogOption.okText ?? '确定'}</ElButton>
    </div>
  };
  windDialog(dynamicDialogOption);
};
/**
 * 异步打开的仅有确认跟取消的对话框
 * @param dialogOption 对话框的各种配置
 */
const windConfirmDialog = (dialogOption: ConfirmDialogOption) => {
  const cancelLoading = reactive<Loading>({ status: false });
  const confirmLoading = reactive<Loading>({ status: false });
  const cancelFunction: footerButtonCallback = (done, loading) => {
    if (dialogOption.cancelCallback) {
      dialogOption.cancelCallback(done, loading);
    } else {
      done();
    }
  };
  const dynamicDialogOption: DynamicDialogOption = {
    defaultSlot: dialogOption.defaultSlot,
    title: dialogOption.title,
    dialogType: dialogOption.dialogType,
    width: dialogOption.width,
    teleportDom: dialogOption.teleportDom,
    footer: (done: (() => void)) => <div>
      <ElButton type={'default'} loading={cancelLoading.status} onClick={() => { cancelFunction(done, cancelLoading); } }>{dialogOption.cancelText ?? '取消'}</ElButton>
      <ElButton type={'primary'} loading={confirmLoading.status} onClick={() => { dialogOption.confirmCallback(done, confirmLoading); }}>{}</ElButton>
    </div>
  };
  windDialog(dynamicDialogOption);
};
/**
 * 异步打开的对话框
 * @param dialogOption 对话框的各种配置
 */
const windDialog = (dialogOption: DynamicDialogOption) => {
  const layerDom = document.createElement('div');
  const visible = reactive<{ status: boolean }>({ status: true });
  const close = () => {
    visible.status = false;
    setTimeout(() => {
      layerDom.remove();
    }, 2000);
  };
  if (!dialogOption.dialogType) dialogOption.dialogType = DialogType.dialog;
  const vNode = <DialogComponent onClose={close} visible={visible} title={dialogOption.title} width={dialogOption.width}
                                 dialogType={dialogOption.dialogType}>
    {{ default: dialogOption.defaultSlot, footer: () => dialogOption.footer && dialogOption.footer(close) }}
  </DialogComponent>;
  window.document.body.appendChild(layerDom);
  vNode.appContext = app._context;
  render(vNode, layerDom);
};

export const MessageService = {
  windConfirm,
  windDialog,
  windConfirmDialog,
  windAlertDialog
};
